package com.foohoo.benchmark.log;

import lombok.extern.slf4j.Slf4j;
import org.openjdk.jmh.annotations.*;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * 测试不同线程数量情况下logback同步打印性能
 * 多线程共2000次, 打印文本1000字节, 线程数是: 1, 2, 4, 8, 16
 * 注: 此处日志大小的计算未包含logback日志模板中打印的时间、线程名称等信息
 * Benchmark                                               Mode  Cnt   Score    Error  Units
 * LogbackWithDiffThread.syncPrintSize100Loop1000Thread1   avgt    3  48.365 ± 31.810  ms/op
 * LogbackWithDiffThread.syncPrintSize100Loop1000Thread16  avgt    3  50.821 ± 72.390  ms/op
 * LogbackWithDiffThread.syncPrintSize100Loop1000Thread2   avgt    3  49.249 ± 33.983  ms/op
 * LogbackWithDiffThread.syncPrintSize100Loop1000Thread4   avgt    3  54.536 ± 41.180  ms/op
 * LogbackWithDiffThread.syncPrintSize100Loop1000Thread8   avgt    3  53.426 ± 49.281  ms/op
 * 一句话结论: 多线程对Logback同步打印的性能没有显著影响
 *
 * @author mzdbxqh
 * @date 2020-10-19 16:42
 **/
@Slf4j
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 5, time = 3)
@Measurement(iterations = 3, time = 3)
@Fork(1)
@State(Scope.Benchmark)
public class LogbackWithDiffThread {

	private static String SIZE_1000;
	private static final int LOOP_TIME_1 = 2048;
	private static final int LOOP_TIME_2 = 1024;
	private static final int LOOP_TIME_4 = 512;
	private static final int LOOP_TIME_8 = 256;
	private static final int LOOP_TIME_16 = 128;

	@Setup
	public void initLogString() {
		char targetChar = "-".charAt(0);
		char[] contentBeforeFill1000 = new char[1000];
		Arrays.fill(contentBeforeFill1000, targetChar);
		SIZE_1000 = String.copyValueOf(contentBeforeFill1000);
	}

	@Threads(1)
	@Benchmark
	public void syncPrintSize100Loop1000Thread1() {
		for (int i = 0; i < LOOP_TIME_1; i++) {
			log.info(SIZE_1000);
		}
	}

	@Threads(2)
	@Benchmark
	public void syncPrintSize100Loop1000Thread2() {
		for (int i = 0; i < LOOP_TIME_2; i++) {
			log.info(SIZE_1000);
		}
	}

	@Threads(4)
	@Benchmark
	public void syncPrintSize100Loop1000Thread4() {
		for (int i = 0; i < LOOP_TIME_4; i++) {
			log.info(SIZE_1000);
		}
	}

	@Threads(8)
	@Benchmark
	public void syncPrintSize100Loop1000Thread8() {
		for (int i = 0; i < LOOP_TIME_8; i++) {
			log.info(SIZE_1000);
		}
	}

	@Threads(16)
	@Benchmark
	public void syncPrintSize100Loop1000Thread16() {
		for (int i = 0; i < LOOP_TIME_16; i++) {
			log.info(SIZE_1000);
		}
	}
}
